import axios from 'axios';
import {message} from 'antd';
import Cookies from 'js-cookie'; // 引入 js-cookie 库
import BackRoute from "../configs/BackRoute";

/**
 * 网络请求工具类
 * 集成请求/响应拦截、错误处理、Cookie 存储 Token（12小时过期）
 * 根据 Cookie 中的 BACK_ROUTE 值选择请求域名：localhost 或 production
 */
class Request {
    // Token 存储键名
    #TOKEN_KEY = 'g3_token';
    // 当前用户信息存储键名
    #CURRENT_USER_INFO_KEY = 'g3_currentUserInfo';
    // 环境选择 Cookie 键名
    #ROUTE_KEY = 'BACK_ROUTE';
    // Token 过期时间：12小时（单位：天，js-cookie 的 expires 单位为天）
    #TOKEN_EXPIRES = 0.5; // 12小时 = 0.5天

    // 保存 navigate 函数的引用
    #navigate = null;

    // 正式环境axios实例
    productionAxiosInstance = axios.create({
        baseURL: BackRoute.productionGatewayIp,
        timeout: 35000,
        headers: {
            'Content-Type': 'application/json;charset=utf-8',
        },
    });

    // 本地axios实例
    localhostAxiosInstance = axios.create({
        baseURL: BackRoute.localhostGatewayIp,
        timeout: 35000,
        headers: {
            'Content-Type': 'application/json;charset=utf-8',
        },
    });

    constructor() {
        // 初始化两个实例的拦截器
        this.initInterceptors(this.productionAxiosInstance);
        this.initInterceptors(this.localhostAxiosInstance);
    }

    // 初始化 navigate 函数（需要在组件中调用）
    initialize(navigate) {
        this.#navigate = navigate;
    }

    // ===================== Token管理 =====================
    /**
     * 设置 Token 到 Cookie（带 12 小时过期时间）
     * @param {string} token - 要存储的 Token
     */
    setToken(token) {
        // 使用 js-cookie 设置 cookie，自动处理编码和解码
        Cookies.set(this.#TOKEN_KEY, token, {
            expires: this.#TOKEN_EXPIRES, // 过期时间：12小时（0.5天）
            path: '/', // 全局生效
            sameSite: 'Lax' // 防止 CSRF 攻击
        });
    }

    /**
     * 从 Cookie 中获取 Token
     * @returns {string|null} - 解析后的 Token（无则返回 null）
     */
    getToken() {
        // 使用 js-cookie 获取 cookie，自动处理解码
        return Cookies.get(this.#TOKEN_KEY) || null;
    }

    /**
     * 清除 Cookie 中的 Token
     */
    clearToken() {
        // 使用 js-cookie 删除 cookie，需与设置时的 path 一致
        Cookies.remove(this.#TOKEN_KEY, {path: '/'});
    }

    // ===================== 当前用户信息管理 =====================
    /**
     * 保存当前的用户信息到本地存储
     * @param userInfo 用户信息
     */
    setCurrentUserInfo(userInfo) {
        localStorage.setItem(this.#CURRENT_USER_INFO_KEY, JSON.stringify(userInfo));
    }

    /**
     * 获取当前的用户信息
     */
    getCurrentUserInfo() {
        return JSON.parse(localStorage.getItem(this.#CURRENT_USER_INFO_KEY));
    }

    // ===================== 环境路由选择 =====================
    /**
     * 获取当前请求使用的 axios 实例
     * @returns {axios.AxiosInstance} - 根据 BACK_ROUTE 选择的 axios 实例
     */
    getAxiosInstance() {
        // 使用 js-cookie 获取环境路由 cookie
        const routeValue = Cookies.get(this.#ROUTE_KEY);
        // 如果 cookie 存在且值为 'localhost'，使用本地实例，否则使用正式环境实例
        return routeValue === 'localhost' ? this.localhostAxiosInstance : this.productionAxiosInstance;
    }

    // ===================== 拦截器初始化 =====================
    initInterceptors(instance) {
        // 请求拦截器：添加 Token 到请求头
        instance.interceptors.request.use(
            (config) => {
                config.headers.Authorization = "Bearer " + this.getToken();
                return config;
            },
            (error) => {
                message.error('请求配置错误');
                return Promise.reject(error);
            }
        );

        // 响应拦截器：处理响应与错误
        instance.interceptors.response.use(
            (response) => {
                const {code, data, message: resMsg} = response.data;

                // 后端编码code返回200, 则直接返回结果
                if (code === 200) {
                    return data;
                }

                message.error(resMsg || '操作失败');
                return Promise.reject(new Error(resMsg || '业务错误'));
            },
            (error) => {
                const {response} = error;

                if (!response) {
                    message.error('网络连接失败，请检查网络');
                    return Promise.reject(error);
                }

                // 401 Token 过期/无效：清除 Token 并跳转登录
                if (response.code === 401) {
                    message.error('登录已过期，请重新登录');
                    this.clearToken();
                    // 使用保存的 navigate 函数
                    if (this.#navigate) {
                        this.#navigate('/login', {replace: true});
                    } else {
                        console.error('navigate 函数未初始化');
                        // 备选方案：使用 window.location
                        window.location.href = '/login';
                    }
                }
                // 403 权限不足
                else if (response.code === 403) {
                    message.error('没有操作权限');
                }
                // 其他错误
                else {
                    message.error(`请求错误: ${response.message}`);
                }
                return Promise.reject(error);
            }
        );
    }

    // ===================== HTTP 请求方法 =====================
    get(url, params = {}, config = {}) {
        return this.getAxiosInstance().get(url, {params, ...config});
    }

    post(url, data = {}, config = {}) {
        return this.getAxiosInstance().post(url, data, config);
    }
}

// 导出单例实例
const RequestUtils = new Request();
export default RequestUtils;